import { defineStore, acceptHMRUpdate } from 'pinia';
import { executeQuery, executeMutation } from 'src/utils/graphqlOperations';
import { apollo } from 'src/boot/apollo';
import { debugLog } from 'src/utils';
import {
  kanvaso,
  kanvasojKanvasoFull,
  kanvasoObjekto,
} from '../queries/queries.js';
import {
  kanvasoEdit,
  kanvasoObjektoLigilo,
  redaktuKanvasojKanvasoObjekto,
} from 'src/queries/mutations.js';

import convertToTree from 'src/utils/treeConverter';
import { KanvasoEventoj } from 'src/queries/subscriptions.js';
import ObjectWrapper from 'src/utils/objectWrapper';
import { EventBus, Events } from '../boot/eventBus';

// Определение интерфейсов и типов
interface KanvasoState {
  kanvaso: any;
  kanvasoObjektoMap: Map<string, ObjectWrapper>;
  kanvasoObjektoCurrentChangesMap: Map<string, ObjectWrapper>;
}

interface QueryResponse {
  data: any;
}

export const useKanvasoStore = defineStore('Kanvaso', {
  state: (): KanvasoState => ({
    kanvaso: null,
    kanvasoObjektoMap: new Map(),
    kanvasoObjektoCurrentChangesMap: new Map(),
  }),
  getters: {
    getCurrentState(state: KanvasoState): Map<string, ObjectWrapper> {
      // Создаем новую карту для хранения актуальных объектов
      const tempMap = new Map(state.kanvasoObjektoMap);

      // Обновляем или удаляем элементы в tempMap на основе текущих изменений
      state.kanvasoObjektoCurrentChangesMap.forEach((change, key) => {
        if (change.isDeleted) {
          tempMap.delete(key);
        } else {
          tempMap.set(key, change);
        }
      });
      return tempMap;
    },
    getMap(): ObjectWrapper[] {
      return Array.from(this.getCurrentState.values());
    },
    getCurrentChangesMap(state: KanvasoState): ObjectWrapper[] {
      return Array.from(state.kanvasoObjektoCurrentChangesMap.values());
    },
    getTree(): ObjectWrapper[] {
      // Преобразуем Map в массив для создания дерева
      const kanvasoObjektoArrFromMap: ObjectWrapper[] = Array.from(
        this.getCurrentState.values(),
      );
      return convertToTree(kanvasoObjektoArrFromMap);
    },

    getKanvaso: (state) => {
      return state.kanvaso;
    },
    getKanvasoLength: (state) => {
      return state.kanvaso ? state.kanvaso.length : 0;
    },
  },
  actions: {
    // Получение информации о канвасе
    async onGetKanvaso(payload): Promise<QueryResponse> {
      const response = await executeQuery(kanvaso, payload, 'on get kanvaso');
      this.kanvaso = response.data.kanvasojKanvaso.edges;
      return response;
    },

    // Получение полной информации о канвасе
    async onGetKanvasoFull(payload): Promise<QueryResponse> {
      const response = await executeQuery(
        kanvasojKanvasoFull,
        payload,
        'on get kanvaso full',
      );
      this.kanvaso = response.data.kanvasojKanvaso.edges;
      return response;
    },

    // Получение объектов канваса
    async onGetKanvasoObjekto(payload): Promise<QueryResponse> {
      const response = await executeQuery(
        kanvasoObjekto,
        payload,
        'on get kanvaso objekto',
      );
      const kanvasoObjektoArr =
        response.data.kanvasojKanvasoObjekto?.edges || [];
      this.kanvasoObjektoMap.clear();
      kanvasoObjektoArr.forEach((item) => {
        if (item.node?.uuid) {
          const obj = new ObjectWrapper(JSON.parse(JSON.stringify(item.node)));
          this.kanvasoObjektoMap.set(obj.uuid, obj);
        }
      });
      return response;
    },

    // Редактирование канваса
    async onEditKanvaso(payload): Promise<boolean> {
      const response = await executeMutation(
        kanvasoEdit,
        payload,
        'on edit kanvaso',
      );
      return response.data?.redaktuKanvasojKanvaso?.status;
    },

    // Редактирование объекта канваса
    async onEditKanvasoObjekto(payload): Promise<boolean> {
      const response = await executeMutation(
        redaktuKanvasojKanvasoObjekto,
        payload,
        'on edit kanvaso objekto',
      );
      return response.data?.redaktuKanvasojKanvasoObjekto?.status;
    },

    // Редактирование связи объекта канваса
    async onEditKanvasoLigilo(payload): Promise<any> {
      const response = await executeMutation(
        kanvasoObjektoLigilo,
        payload,
        'on edit kanvaso ligilo',
      );
      return response;
    },

    //Очистка хранилища
    clearKanvasoStore() {
      this.$reset();
      debugLog('kanvaso store cleared');
    },

    // Подписка на события канваса
    async onKanvasoSubscribe(payload): Promise<any> {
      debugLog('on kanvaso subscribe');

      return apollo.default
        .subscribe({
          query: KanvasoEventoj,
          variables: payload,
        })
        .subscribe({
          next: (data) => {
            const evento = data.data.KanvasoEventoj;
            if (evento?.objekto) {
              const obj = new ObjectWrapper(
                JSON.parse(JSON.stringify(evento.objekto)),
              );

              if (
                this.kanvasoObjektoMap.has(obj.uuid) ||
                this.kanvasoObjektoCurrentChangesMap.has(obj.uuid)
              ) {
                this.kanvasoObjektoCurrentChangesMap.set(obj.uuid, obj);

                if (obj.isDeleted) {
                  EventBus.$emit(Events.Delete, obj.uuid, obj);
                  console.log('delete:', obj.uuid);
                } else {
                  EventBus.$emit(Events.Change, obj.uuid, obj);
                  console.log('change:', obj.uuid);
                }
              } else {
                this.kanvasoObjektoCurrentChangesMap.set(obj.uuid, obj);

                EventBus.$emit(Events.Create, obj.parentUuid, obj);
                console.log('add:', obj.uuid);
              }
            }
          },
          error: (err) => {
            console.error('KanvasoEventoj subscription error:', err);
          },
        });
    },
  },
});
//@ts-ignore
if (import.meta.hot) {
  //@ts-ignore
  import.meta.hot.accept(acceptHMRUpdate(useKanvasoStore, import.meta.hot));
}
